using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Builder
{
  public partial class BuildScreen : Form
  {
    private PlayerBuild m_PlayerBuildData;
    private ApproxTrainingPct m_atpForm;

    private Boolean m_Autobuilding = false;
    private Boolean m_StopAutobuild = false;


    public BuildScreen()
    {
      InitializeComponent();

    }

    public void Initialize(PlayerBuild PlayerBld)
    {

      m_PlayerBuildData = PlayerBld;
      cmbxGamesOn.Text = PlayerBld.GameDays;
      //fill softcap targets
      cmbxSoftcaps.Items.Clear();
      foreach (KeyValuePair<int, SoftcapRange> kvp in m_PlayerBuildData.Softcaps)
      {
        if (kvp.Value.Start > 0)
        {
          cmbxSoftcaps.Items.Add(kvp.Value.Start.ToString());
          cmbxAutobuildTargetCap.Items.Add(kvp.Value.Start.ToString());
        }
      }
      cmbxSoftcaps.SelectedIndex = 0;
      cmbxAttr1.SelectedIndex = 0;
      cmbxGoalSkill.SelectedIndex = 0;
      cmbxSPSkill.SelectedIndex = 0;
      UpdateLabels();
      DataGridViewRow dgvr = new DataGridViewRow();
      dgvr.CreateCells(dtgrdvwDailyLook);
      //intensity,attr1,pct,attr2,pct
      //season/day, TOTAL BUILD SP, str,blk,spd,tck,agi,thr,jum,cat,sta,car,vis,kck,con,pun
      dgvr.Cells[0].Value = Utility.GetSeasonDayString(m_PlayerBuildData.Season, m_PlayerBuildData.Day);
      RefreshDailyLookGridRow(dgvr);
      dtgrdvwDailyLook.Rows.Add(dgvr);
      //enable game today button?
      btnProcessGame.Enabled = Utility.GameToday(m_PlayerBuildData.Day, m_PlayerBuildData.GameDays);
    }

    private void UpdateLabels()
    {
      this.Text = "Daily Player Builder - " + m_PlayerBuildData.PlayerName;
      if (m_PlayerBuildData.UnspentBT > 8)
      {
        lblBTAvail.BackColor = Color.LightSalmon;
      }
      else
      {
        lblBTAvail.BackColor = SystemColors.Control;
      }
      lblBTAvail.Text = m_PlayerBuildData.UnspentBT.ToString();
      lblSPAvail.Text = m_PlayerBuildData.UnspentSP.ToString();
      lblBoosts.Text = m_PlayerBuildData.UnspentBoosts.ToString();
      lblVetSPAvail.Text = m_PlayerBuildData.UnspentVetSP.ToString();
      lblMaxGameXPPct.Text = "Max Game XP % = " + m_PlayerBuildData.MaxGameXPPct.ToString();

      if (m_PlayerBuildData.UnspentTP > 14)
      {
        lblTPAvail.BackColor = Color.LightSalmon;
      }
      else
      {
        lblTPAvail.BackColor = SystemColors.Control;
      }
      lblTPAvail.Text = m_PlayerBuildData.UnspentTP.ToString();

      lblSeasonDay.Text = Utility.GetSeasonDayString(m_PlayerBuildData.Season, m_PlayerBuildData.Day);
    }

    private void Enable()
    {
      if (rdbtnIntense.Checked)
      {
        cmbxAttr1.Enabled = true;
        cmbxAttr2.Enabled = true;
        chckNoActivity.Enabled = false;
      }
      else if (rdbtnNormal.Checked)
      {
        cmbxAttr1.Enabled = true;
        cmbxAttr2.Enabled = false;
        chckNoActivity.Enabled = true;
      }
      else
      {
        cmbxAttr1.Enabled = false;
        cmbxAttr2.Enabled = false;
        chckNoActivity.Enabled = false;
      }
      SetValidIntenseCombos();
    }

    private void rdbtnIntense_Click(object sender, EventArgs e)
    {
      Enable();
    }

    private void cmbxAttr1_SelectedIndexChanged(object sender, EventArgs e)
    {
      SetValidIntenseCombos();
    }

    private void SetValidIntenseCombos()
    {
      cmbxAttr2.Items.Clear();
      switch (cmbxAttr1.Text)
      {
        case "strength":
          cmbxAttr2.Items.Add("blocking");
          cmbxAttr2.Items.Add("jumping");
          cmbxAttr2.Items.Add("carrying");
          cmbxAttr2.Items.Add("throwing");
          cmbxAttr2.Items.Add("kicking");
          cmbxAttr2.Items.Add("punting");
          cmbxAttr2.Items.Add("tackling");
          break;
        case "speed":
          cmbxAttr2.Items.Add("stamina");
          cmbxAttr2.Items.Add("agility");
          cmbxAttr2.Items.Add("tackling");
          break;
        case "agility":
          cmbxAttr2.Items.Add("blocking");
          cmbxAttr2.Items.Add("stamina");
          cmbxAttr2.Items.Add("speed");
          cmbxAttr2.Items.Add("vision");
          cmbxAttr2.Items.Add("throwing");
          cmbxAttr2.Items.Add("tackling");
          break;
        case "stamina":
          cmbxAttr2.Items.Add("agility");
          cmbxAttr2.Items.Add("jumping");
          cmbxAttr2.Items.Add("speed");
          cmbxAttr2.Items.Add("confidence");
          break;
        case "tackling":
          cmbxAttr2.Items.Add("agility");
          cmbxAttr2.Items.Add("jumping");
          cmbxAttr2.Items.Add("speed");
          cmbxAttr2.Items.Add("strength");
          break;
        case "blocking":
          cmbxAttr2.Items.Add("agility");
          cmbxAttr2.Items.Add("strength");
          break;
        case "carrying":
          cmbxAttr2.Items.Add("catching");
          cmbxAttr2.Items.Add("confidence");
          cmbxAttr2.Items.Add("strength");
          break;
        case "jumping":
          cmbxAttr2.Items.Add("strength");
          cmbxAttr2.Items.Add("stamina");
          cmbxAttr2.Items.Add("catching");
          cmbxAttr2.Items.Add("vision");
          cmbxAttr2.Items.Add("tackling");
          break;
        case "vision":
          cmbxAttr2.Items.Add("confidence");
          cmbxAttr2.Items.Add("agility");
          cmbxAttr2.Items.Add("throwing");
          cmbxAttr2.Items.Add("catching");
          cmbxAttr2.Items.Add("kicking");
          cmbxAttr2.Items.Add("punting");
          cmbxAttr2.Items.Add("jumping");
          break;
        case "confidence":
          cmbxAttr2.Items.Add("stamina");
          cmbxAttr2.Items.Add("vision");
          cmbxAttr2.Items.Add("carrying");
          break;
        case "catching":
          cmbxAttr2.Items.Add("jumping");
          cmbxAttr2.Items.Add("vision");
          cmbxAttr2.Items.Add("carrying");
          break;
        case "throwing":
          cmbxAttr2.Items.Add("strength");
          cmbxAttr2.Items.Add("vision");
          cmbxAttr2.Items.Add("agility");
          break;
        case "punting":
          cmbxAttr2.Items.Add("strength");
          cmbxAttr2.Items.Add("vision");
          break;
        case "kicking":
          cmbxAttr2.Items.Add("strength");
          cmbxAttr2.Items.Add("vision");
          break;
      }
    }

    #region Training Grid
    private void btnTrain_Click(object sender, EventArgs e)
    {
      if (rdbtnNormal.Checked)
      {
        if (cmbxAttr1.Text.Trim().Length > 0)
        {
          AddTraining();
        }
        else
        {
          MessageBox.Show("Please select a training option");
          cmbxAttr1.Select();
        }
      }
      else
      {
        if (cmbxAttr1.Text.Trim() != "" && cmbxAttr2.Text.Trim() != "")
        {
          AddTraining();
        }
        else
        {
          MessageBox.Show("Please select all training options");
          cmbxAttr1.Select();
        }
      }
    }

    private void btnRemoveTraining_Click(object sender, EventArgs e)
    {
      RemoveSelectedTrainingRow();
    }

    private void dtgrdvwTraining_KeyUp(object sender, KeyEventArgs e)
    {
      if (e.KeyValue == 46)
      {
        RemoveSelectedTrainingRow();
      }
    }

    private void RemoveSelectedTrainingRow()
    {
      if (dtgrdvwTraining.Rows.Count > 0 && dtgrdvwTraining.SelectedRows.Count == 1)
      {
        switch (dtgrdvwTraining.SelectedRows[0].Cells[0].Value.ToString())
        {
          case TrainingLevelStrings.NORMAL:
            //remove the row
            dtgrdvwTraining.Rows.Remove(dtgrdvwTraining.SelectedRows[0]);
            break;
          case TrainingLevelStrings.INTENSE:
            dtgrdvwTraining.Rows.Remove(dtgrdvwTraining.SelectedRows[0]);
            break;
        }
        UpdateLabels();
      }
    }

    private void RemoveAllTraining()
    {
      while (dtgrdvwTraining.Rows.Count > 0)
      {
        if (dtgrdvwTraining.SelectedRows.Count == 0)
        {
          dtgrdvwTraining.ClearSelection();
        }
        RemoveSelectedTrainingRow();
      }
    }

    private void RemoveAllSP()
    {
      while (dtrgdvwSPSpent.Rows.Count > 0)
      {
        if (dtrgdvwSPSpent.SelectedRows.Count == 0)
        {
          dtrgdvwSPSpent.ClearSelection();
        }
        RemoveSelectedSPRow();
      }
    }


    private void AddTraining()
    {
      string SeasonDay = Utility.GetSeasonDayString(m_PlayerBuildData.Season, m_PlayerBuildData.Day);
      if (rdbtnNormal.Checked)
      {
        //AddNormalTrain
        DataGridViewRow dgvr = new DataGridViewRow();
        //intensity,attr1,pct,attr2,pct
        dgvr.CreateCells(dtgrdvwTraining);
        dgvr.Cells[0].Value = TrainingLevelStrings.NORMAL;
        dgvr.Cells[1].Value = cmbxAttr1.Text;

        int ApproxTrainPct = m_PlayerBuildData.ApproxTrainPercentage(SeasonDay, cmbxAttr1.Text);

        if (chckNoActivity.Checked)
        {
          dgvr.Cells[2].Value = Math.Round(ApproxTrainPct * 1.075);
          dgvr.Cells[5].Value = true;
        }
        else
        {
          dgvr.Cells[2].Value = ApproxTrainPct;
          dgvr.Cells[5].Value = false;
        }

        dtgrdvwTraining.Rows.Add(dgvr);
      }
      else if (rdbtnIntense.Checked)
      {
        //AddIntense
        DataGridViewRow dgvr = new DataGridViewRow();
        //intensity,attr1,pct,attr2,pct
        dgvr.CreateCells(dtgrdvwTraining);
        dgvr.Cells[0].Value = TrainingLevelStrings.INTENSE;
        dgvr.Cells[1].Value = cmbxAttr1.Text;
        int ApproxTrainPct = m_PlayerBuildData.ApproxTrainPercentage(SeasonDay, cmbxAttr1.Text);
        dgvr.Cells[2].Value = Math.Round(ApproxTrainPct * 1.25, 0);
        dgvr.Cells[3].Value = cmbxAttr2.Text;
        ApproxTrainPct = m_PlayerBuildData.ApproxTrainPercentage(SeasonDay, cmbxAttr2.Text);
        dgvr.Cells[4].Value = Math.Round(ApproxTrainPct * 1.25, 0);
        dgvr.Cells[5].Value = false;
        dtgrdvwTraining.Rows.Add(dgvr);
      }
    }
    #endregion

    #region SP Grid
    private void btnAddSkillSP_Click(object sender, EventArgs e)
    {
      int SPToAdd = (int)spnSPToAdd.Value;
      if (cmbxSPSkill.Text.Trim().Length > 0 && SPToAdd > 0 && SPToAdd <= m_PlayerBuildData.UnspentSP)
      {
        //AddSkillPoints Spent
        DataGridViewRow dgvr = new DataGridViewRow();
        //intensity,attr1,pct,attr2,pct
        dgvr.CreateCells(dtrgdvwSPSpent);
        dgvr.Cells[0].Value = cmbxSPSkill.Text;
        dgvr.Cells[1].Value = SPToAdd.ToString();
        dtrgdvwSPSpent.Rows.Add(dgvr);
        m_PlayerBuildData.SpendSkillPoints(-SPToAdd);
        UpdateLabels();
        RefreshGoalGrid();
      }
      else if (SPToAdd > m_PlayerBuildData.UnspentSP)
      {
        MessageBox.Show("You do not have enough free Skill Points.");
      }
    }

    private void btnRemoveSkillSP_Click(object sender, EventArgs e)
    {
      RemoveSelectedSPRow();
      RefreshGoalGrid();
    }

    private void RemoveSelectedSPRow()
    {
      if (dtrgdvwSPSpent.Rows.Count > 0 && dtrgdvwSPSpent.SelectedRows.Count == 1)
      {
        m_PlayerBuildData.SpendSkillPoints(int.Parse(dtrgdvwSPSpent.SelectedRows[0].Cells[1].Value.ToString()));
        UpdateLabels();
        dtrgdvwSPSpent.Rows.Remove(dtrgdvwSPSpent.SelectedRows[0]);
      }
    }
    #endregion

    #region Daily Processing
    private void btnProcess_Click(object sender, EventArgs e)
    {
      ProcessTrainingAndSP();
    }

    /// <summary>
    /// Commits the traingin and SP to the build
    /// </summary>
    private void ProcessTrainingAndSP()
    {
      CommitCurrentChanges(true, true, true);
      RefreshGoalGrid();
      UpdateLabels();
    }

    private void btnResetCurrent_Click(object sender, EventArgs e)
    {
      ResetCurrentDay();
    }

    private void ResetCurrentDay()
    {
      try
      {

        //Now back off the current player day, and start over
        m_PlayerBuildData.RestartCurrentDay(false);
        btnProcessGame.Enabled = Utility.GameToday(m_PlayerBuildData.Day, m_PlayerBuildData.GameDays);
        UpdateLabels();
        RefreshGoalGrid();
        RefreshDailyLookGridRow(dtgrdvwDailyLook.Rows[dtgrdvwDailyLook.Rows.Count - 1]);
      }
      catch (Exception ex)
      {
        Utility.ShowErrorMesssage(ex, "Error trying to rollback a day.  It is suggested that you rebuild this player from scratch.");
      }
    }


    private void btnNightlyProcessing_Click(object sender, EventArgs e)
    {
      //Warning about uncommitted training/SP
      if (dtgrdvwTraining.Rows.Count > 0 || dtrgdvwSPSpent.Rows.Count > 0)
      {
        DialogResult dr = Utility.QuestionBox(String.Format("You have {0} training records and {1} Skill Points records uncommitted.  Do you wish to commit these rows before processing the nightly rollover?", dtgrdvwTraining.Rows.Count, dtrgdvwSPSpent.Rows.Count), MessageBoxButtons.YesNoCancel);
        if (dr == DialogResult.Yes)
        {
          //process training
          ProcessTrainingAndSP();
        }
        else if (dr == DialogResult.No)
        {
          //remove training
          RemoveAllSP();
          RemoveAllTraining();
        }
        else
        {
          //cancel click
          return;
        }
      }
      //Attempt to processgame, will only go through if the game has not already been processed.
      StartNewDay();
      DailyLookSelectLastRow();
    }

    private void btnProcessGame_Click(object sender, EventArgs e)
    {
      m_PlayerBuildData.ProcessGame();
      (sender as Button).Enabled = false;
      RefreshDailyLookGridRow(dtgrdvwDailyLook.Rows[dtgrdvwDailyLook.Rows.Count - 1]);
      RefreshGoalGrid();
      UpdateLabels();
    }


    private void CommitCurrentChanges(Boolean ClearSkills, Boolean ClearTraining, Boolean ShowNSFWarnings)
    {
      int TPUsed = 0;
      int SPUsed = 0;
      int BTEarned = 0;
      //Perform training on skills
      string SeasonDay = Utility.GetSeasonDayString(m_PlayerBuildData.Season, m_PlayerBuildData.Day);
      #region Training
      if (dtgrdvwTraining.Rows.Count > 0)
      {
        for (int RowIndex = 0; RowIndex < dtgrdvwTraining.Rows.Count; RowIndex++)
        {
          //intensity,attr1,%,attr2,%

          switch (dtgrdvwTraining.Rows[RowIndex].Cells[0].Value.ToString())
          {
            case TrainingLevelStrings.NORMAL:
              if (m_PlayerBuildData.UnspentTP >= 2)
              {
                m_PlayerBuildData.SpendTrainingPoints(-2);
                double TrainingModifier = 100.0;
                if (Boolean.Parse(dtgrdvwTraining.Rows[RowIndex].Cells[5].Value.ToString()))
                {
                  TrainingModifier = 107.5;
                }
                m_PlayerBuildData.TrainAttribute(SeasonDay, dtgrdvwTraining.Rows[RowIndex].Cells[1].Value.ToString(), TrainingModifier);
                TPUsed += 2;
              }
              else if (ShowNSFWarnings)
              {
                Utility.ShowWarningMessage(string.Format("You do not have enough training points to process training number {0}", RowIndex + 1), "Insufficient Training Points");
              }
              break;
            case TrainingLevelStrings.INTENSE:
              if (m_PlayerBuildData.UnspentTP >= 5)
              {
                m_PlayerBuildData.SpendTrainingPoints(-5);
                m_PlayerBuildData.TrainAttribute(SeasonDay, dtgrdvwTraining.Rows[RowIndex].Cells[1].Value.ToString(), 125);
                m_PlayerBuildData.TrainAttribute(SeasonDay, dtgrdvwTraining.Rows[RowIndex].Cells[3].Value.ToString(), 125);
                //intense
                m_PlayerBuildData.SpendBonusTokens(1);
                TPUsed += 5;
                BTEarned++;
              }
              else if (ShowNSFWarnings)
              {
                Utility.ShowWarningMessage(string.Format("You do not have enough training points to process training number {0}", RowIndex + 1), "Insufficient Training Points");
              }
              break;
          }
        }
      }
      #endregion

      #region SP
      if (dtrgdvwSPSpent.Rows.Count > 0)
      {
        int SPsToAddBack = 0;
        for (int RowIndex = 0; RowIndex < dtrgdvwSPSpent.Rows.Count; RowIndex++)
        {
          //intensity,attr1,%,attr2,%
          int SPToSpend = int.Parse(dtrgdvwSPSpent.Rows[RowIndex].Cells[1].Value.ToString());
          SPUsed += SPToSpend;
          SPsToAddBack += m_PlayerBuildData.AddSkillPoints(SeasonDay, dtrgdvwSPSpent.Rows[RowIndex].Cells[0].Value.ToString(), SPToSpend);
          SPUsed = SPUsed - SPsToAddBack;
        }
        m_PlayerBuildData.SpendSkillPoints(SPsToAddBack);
        UpdateLabels();
      }
      #endregion

      if (ClearSkills)
      {
        dtrgdvwSPSpent.Rows.Clear();
      }
      if (ClearTraining)
      {
        dtgrdvwTraining.Rows.Clear();
      }

      #region Add Grid Row
      DataGridViewRow dgvr = dtgrdvwDailyLook.Rows[dtgrdvwDailyLook.Rows.Count - 1];
      //season/day, TOTAL BUILD SP, str,blk,spd,tck,agi,thr,jum,cat,sta,car,vis,kck,con,pun
      dgvr.Cells[0].Value = Utility.GetSeasonDayString(m_PlayerBuildData.Season, m_PlayerBuildData.Day);
      //add to existing grid amounts.
      PlayerDay pd = m_PlayerBuildData.GetPlayerDay(dgvr.Cells[0].Value.ToString());
      pd.SPSpent += SPUsed;//         SPUsed += int.Parse(dgvr.Cells[16].Value.ToString());
      pd.TPSpent += TPUsed;//         TPUsed += int.Parse(dgvr.Cells[17].Value.ToString());
      pd.BTEarned += BTEarned;//      BTEarned += int.Parse(dgvr.Cells[18].Value.ToString());
      //pd.BTSpent += m_SpentBTs;//      m_SpentBTs += int.Parse(dgvr.Cells[19].Value.ToString());
      RefreshDailyLookGridRow(dgvr);
      //m_SpentBTs = 0;
      #endregion

    }

    private void RefreshDailyLookGridRow(DataGridViewRow dgvr)//, int SPUsed, int TPUsed, int BTEarned, int SpentBTs)
    {
      dgvr.Cells[6].Value = m_PlayerBuildData.TotalSkillPointsInBuild(dgvr.Cells[0].Value.ToString()).ToString();
      PlayerDay pd = m_PlayerBuildData.GetPlayerDay(dgvr.Cells[0].Value.ToString());

      //gamexp
      dgvr.Cells[1].Value = pd.GameXP;
      //dailyxp
      dgvr.Cells[2].Value = pd.DailyXP;
      //vet xp
      dgvr.Cells[3].Value = m_PlayerBuildData.VetXP;
      //tot xp
      dgvr.Cells[4].Value = m_PlayerBuildData.XP;
      //level
      dgvr.Cells[5].Value = m_PlayerBuildData.Level;
      dgvr.Cells[7].Value = pd.RunningBuildTotals[AttributeStrings.STR].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["strength"].TrainingBarPct.ToString("D2");
      dgvr.Cells[8].Value = pd.RunningBuildTotals[AttributeStrings.BLK].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["blocking"].TrainingBarPct.ToString("D2");
      dgvr.Cells[9].Value = pd.RunningBuildTotals[AttributeStrings.SPD].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["speed"].TrainingBarPct.ToString("D2");
      dgvr.Cells[10].Value = pd.RunningBuildTotals[AttributeStrings.TCK].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["tackling"].TrainingBarPct.ToString("D2");
      dgvr.Cells[11].Value = pd.RunningBuildTotals[AttributeStrings.AGI].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["agility"].TrainingBarPct.ToString("D2");
      dgvr.Cells[12].Value = pd.RunningBuildTotals[AttributeStrings.THR].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["throwing"].TrainingBarPct.ToString("D2");
      dgvr.Cells[13].Value = pd.RunningBuildTotals[AttributeStrings.JUM].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["jumping"].TrainingBarPct.ToString("D2");
      dgvr.Cells[14].Value = pd.RunningBuildTotals[AttributeStrings.CAT].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["catching"].TrainingBarPct.ToString("D2");
      dgvr.Cells[15].Value = pd.RunningBuildTotals[AttributeStrings.STA].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["stamina"].TrainingBarPct.ToString("D2");
      dgvr.Cells[16].Value = pd.RunningBuildTotals[AttributeStrings.CAR].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["carrying"].TrainingBarPct.ToString("D2");
      dgvr.Cells[17].Value = pd.RunningBuildTotals[AttributeStrings.VIS].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["vision"].TrainingBarPct.ToString("D2");
      dgvr.Cells[18].Value = pd.RunningBuildTotals[AttributeStrings.KCK].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["kicking"].TrainingBarPct.ToString("D2");
      dgvr.Cells[19].Value = pd.RunningBuildTotals[AttributeStrings.CON].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["confidence"].TrainingBarPct.ToString("D2");
      dgvr.Cells[20].Value = pd.RunningBuildTotals[AttributeStrings.PUN].GetAttributeAmountForDisplay() + " / " + pd.RunningBuildTotals["punting"].TrainingBarPct.ToString("D2");
      //SPSpent
      dgvr.Cells[21].Value = pd.SPSpent;// SPUsed.ToString();
      //TPSpent
      dgvr.Cells[22].Value = pd.TPSpent;// TPUsed.ToString(); 
      //BT Earned
      dgvr.Cells[23].Value = pd.BTEarned;// BTEarned.ToString();
      //BT Spent
      dgvr.Cells[24].Value = pd.BTSpent;// SpentBTs.ToString();
      //BT Spent
      dgvr.Cells[25].Value = pd.BoostsUsed;
      dgvr.Cells[26].Value = pd.VetSPSpent;
    }

    private void ProcessLevelBonus()
    {
      //TODO: Processing Level Bonus should be handled completely inside the PlayerBuild Object
      //when an XP rollover occurs.
      /*
      //process tomorrow's level bonus, if a level up occurs during tomorrow's daily XP or game.
      //Do we need to process a level bonus for this day?
      int ThisLevel = int.Parse(m_PlayerDataGrid.Rows[m_CurrentRow].Cells[4].Value.ToString());

      if (dtgrdvwDailyLook.Rows.Count == 1)
      {
         if (ThisLevel > m_StartingLevel)
         {
            //level bonus!
            m_PlayerBuildData.ProcessLevelBonus(ThisLevel);
         }
      }
      else
      {
         if (m_PlayerDataGrid.Rows.Count > (m_CurrentRow + 1) && ThisLevel < int.Parse(m_PlayerDataGrid.Rows[m_CurrentRow + 1].Cells[4].Value.ToString()))
         {
            //level bonus!
            m_PlayerBuildData.ProcessLevelBonus(ThisLevel);
         }
      }*/
    }

    /// <summary>
    /// Prepares the screen for a new day.  Adds the day's row to the grid.  
    /// </summary>
    private void StartNewDay()
    {
      //call processgame, to make sure we don't miss processing a game.
      m_PlayerBuildData.ProcessGame();
      //refresh the grid before moving on.
      RefreshDailyLookGridRow(dtgrdvwDailyLook.Rows[dtgrdvwDailyLook.Rows.Count - 1]);
      //now start the actual rollover
      string SeasonDay = m_PlayerBuildData.NightlyProcessing();
      //now add a new row to the daily look grid, and refresh it
      DataGridViewRow dgvr = new DataGridViewRow();
      dgvr.CreateCells(dtgrdvwDailyLook);
      dgvr.Cells[0].Value = SeasonDay;
      RefreshDailyLookGridRow(dgvr);
      dtgrdvwDailyLook.Rows.Add(dgvr);
      UpdateLabels();
      RefreshGoalGrid();
      //enable game today button?
      btnProcessGame.Enabled = Utility.GameToday(m_PlayerBuildData.Day, m_PlayerBuildData.GameDays);

    }



    private void btnBackupOneDay_Click(object sender, EventArgs e)
    {
      if (m_PlayerBuildData.PlayerDays.Count > 2)
      {
        Rollback();
      }
      else
      {
        Utility.ShowInfoMessage("You've reached the beginning of this build", "Beginning Reached");
      }
    }

    //performs a rollback of the current day.
    private void Rollback()
    {
      m_PlayerBuildData.RestartCurrentDay(true);
      UpdateLabels();
      RefreshGoalGrid();
      //remove last row
      dtgrdvwDailyLook.Rows.Remove(dtgrdvwDailyLook.Rows[dtgrdvwDailyLook.Rows.Count - 1]);
      RefreshDailyLookGridRow(dtgrdvwDailyLook.Rows[dtgrdvwDailyLook.Rows.Count - 1]);
    }

    private void SplitSPFromPct(string AttributeGridCellText, out string SP, out string Pct)
    {
      int Pos = AttributeGridCellText.IndexOf("/");
      SP = AttributeGridCellText.Substring(0, Pos);
      Pct = AttributeGridCellText.Substring(Pos + 1, AttributeGridCellText.Length - (Pos + 1));
    }
    #endregion

    private void BuildScreen_Shown(object sender, EventArgs e)
    {
      Enable();
    }


    /// <summary>
    /// if not enough SP, set to number of SP available
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void spnSPToAdd_ValueChanged(object sender, EventArgs e)
    {
      if ((int)spnSPToAdd.Value > m_PlayerBuildData.UnspentSP)
      {
        spnSPToAdd.Value = m_PlayerBuildData.UnspentSP;
      }
    }




    #region Cap Goal Tracking


    private void btnRemoveCapGoal_Click(object sender, EventArgs e)
    {
      RemoveCapGoalRow();
    }

    private void dtgrdvwTargets_KeyUp(object sender, KeyEventArgs e)
    {
      if (e.KeyValue == 46)
      {
        RemoveCapGoalRow();
      }
    }

    private void RemoveCapGoalRow()
    {
      if (dtgrdvwTargets.Rows.Count > 0 && dtgrdvwTargets.SelectedRows.Count == 1)
      {
        dtgrdvwTargets.Rows.Remove(dtgrdvwTargets.SelectedRows[0]);
      }
    }

    private void btnAddCapGoal_Click(object sender, EventArgs e)
    {
      if (cmbxGoalSkill.Text.Trim().Length > 0 && cmbxSoftcaps.Text.Trim().Length > 0)
      {
        DataGridViewRow dgvr = new DataGridViewRow();
        dgvr.CreateCells(dtgrdvwTargets);
        dgvr.Cells[0].Value = cmbxGoalSkill.Text;
        dgvr.Cells[1].Value = cmbxSoftcaps.Text;
        dtgrdvwTargets.Rows.Add(dgvr);
        //add the skill and target cap, then call RefreshGoalGrid
        RefreshGoalGrid();
      }
    }

    private void RefreshGoalGrid()
    {
      //Cycle through the grid.  For each attribute, get it's current level & train % from the DailyLook grid
      //then spend SPs on the attribute up to the target cap.  If this amount = or exceeds the target cap, color it green.
      //otherwise color it red.
      foreach (DataGridViewRow row in dtgrdvwTargets.Rows)
      {
        string Attr = row.Cells[0].Value.ToString();
        double AttrLevel = 0;
        int TrainPct = 0;
        string SeasonDay = Utility.GetSeasonDayString(m_PlayerBuildData.Season, m_PlayerBuildData.Day);

        PlayerDay pd = m_PlayerBuildData.GetPlayerDay(SeasonDay);

        if (pd.RunningBuildTotals.ContainsKey(Attr))
        {
          AttrLevel = pd.RunningBuildTotals[Attr].CurrentAmount;
          TrainPct = pd.RunningBuildTotals[Attr].TrainingBarPct;
        }
        row.Cells[4].Value = TrainPct;
        double MaxAttrLevel = GetMaxGoalAttrLevel(AttrLevel, m_PlayerBuildData.UnspentSP);
        row.Cells[2].Value = MaxAttrLevel;
        //now color the cell green if it's over, yellow if close (within 6, red if farther)
        double TargetAttrLevel = double.Parse(row.Cells[1].Value.ToString());
        //cell 3 is the SPs to target
        row.Cells[3].Value = GetSPsToGoalAttrLevel(AttrLevel, TargetAttrLevel);
        DataGridViewCellStyle dtgrdvwCellStyle = new DataGridViewCellStyle();
        if (MaxAttrLevel >= TargetAttrLevel)
        {
          dtgrdvwCellStyle.BackColor = Color.LightGreen;
          dtgrdvwCellStyle.ForeColor = Color.Black;
        }
        else if (MaxAttrLevel >= TargetAttrLevel - 6)
        {
          dtgrdvwCellStyle.BackColor = Color.LightYellow;
          dtgrdvwCellStyle.ForeColor = Color.Black;
        }
        else
        {
          dtgrdvwCellStyle.BackColor = Color.LightSalmon;
          dtgrdvwCellStyle.ForeColor = Color.Black;
        }
        row.Cells[2].Style = dtgrdvwCellStyle;

      }

    }

    /// <summary>
    /// For the passed skill points and attribute level, this returns the attribute with all possible SPs added.
    /// </summary>
    /// <param name="CurrentLevel"></param>
    /// <param name="SkillPointsToAdd"></param>
    /// <returns></returns>
    private double GetMaxGoalAttrLevel(double CurrentAttrLevel, int SkillPointsToAdd)
    {
      int SpentSPs = 0;

      int SPsToMoveSkillByOne = m_PlayerBuildData.GetSoftcapSkillPointsByAttrAmount(CurrentAttrLevel);
      //spend one SP, and recalculate until SPs are gone.
      while (SpentSPs <= SkillPointsToAdd - SPsToMoveSkillByOne)
      {
        //move skill by one and recalc softcap
        CurrentAttrLevel++;
        SpentSPs += SPsToMoveSkillByOne;
        SPsToMoveSkillByOne = m_PlayerBuildData.GetSoftcapSkillPointsByAttrAmount(CurrentAttrLevel);
      }
      return CurrentAttrLevel;
    }


    /// <summary>
    /// For the passed attribute level & goal, this returns the number if SPs needed to attain that goal.
    /// </summary>
    /// <param name="CurrentAttrLevel"></param>
    /// <param name="Goal"></param>
    /// <returns></returns>
    private int GetSPsToGoalAttrLevel(double CurrentAttrLevel, double Goal)
    {
      int SpentSPs = 0;

      int SPsToMoveSkillByOne = m_PlayerBuildData.GetSoftcapSkillPointsByAttrAmount(CurrentAttrLevel);
      //spend one SP, and recalculate until SPs are gone.
      while (CurrentAttrLevel < Goal)
      {
        //move skill by one and recalc softcap
        CurrentAttrLevel++;
        SpentSPs += SPsToMoveSkillByOne;
        SPsToMoveSkillByOne = m_PlayerBuildData.GetSoftcapSkillPointsByAttrAmount(CurrentAttrLevel);
      }
      return SpentSPs;
    }

    #endregion


    private void btnBTToSP_Click(object sender, EventArgs e)
    {
      if (m_PlayerBuildData.UnspentBT >= 4)
      {
        m_PlayerBuildData.SpendBonusTokens(-4);
        m_PlayerBuildData.SpendSkillPoints(1);
        PlayerDay pd = m_PlayerBuildData.GetPlayerDay(Utility.GetSeasonDayString(m_PlayerBuildData.Season, m_PlayerBuildData.Day));
        pd.BTSpent += 4;
        pd.SPEarned += 1;
        RefreshDailyLookGridRow(dtgrdvwDailyLook.Rows[dtgrdvwDailyLook.Rows.Count - 1]);
        UpdateLabels();
        RefreshGoalGrid();
      }
    }

    private void BuildScreen_FormClosed(object sender, FormClosedEventArgs e)
    {
      //free the atpForm if it's displayed.
      if (m_atpForm != null && !m_atpForm.IsDisposed)
      {
        m_atpForm.Dispose();
      }
    }

    private void btnSaveGrid_Click(object sender, EventArgs e)
    {
      saveFileDialog1.Filter = "Tab Delimited|*.txt|Comma Delimited|*.csv";
      saveFileDialog1.Title = "Save Player to File";
      if (saveFileDialog1.ShowDialog() == DialogResult.OK)
      {
        StringBuilder data = null;
        switch (saveFileDialog1.FilterIndex)
        {
          case 1:
            //save tab delimited
            data = GetGridDelimited("\t", true);
            break;
          case 2:
            //save comma delimited
            data = GetGridDelimited(",", true);
            break;
        }
        if (data != null)
        {
          try
          {
            using (System.IO.StreamWriter sr = new System.IO.StreamWriter(saveFileDialog1.FileName))
            {
              sr.Write(data.ToString());
              sr.Flush();
              sr.Close();
            }
          }
          catch (Exception ex)
          {
            Utility.ShowErrorMesssage(ex, string.Format("Unable to save to file {0}", saveFileDialog1.FileName));
          }
        }
      }
    }

    private StringBuilder GetGridDelimited(string Delimiter, Boolean IncludeHeaderRow)
    {
      StringBuilder sb = new StringBuilder();
      if (IncludeHeaderRow)
      {
        //Add a header row
        foreach (DataGridViewColumn clm in dtgrdvwDailyLook.Columns)
        {
          if (clm.Index != 0)
          {
            sb.Append(Delimiter);
          }
          sb.Append(clm.HeaderText);
        }

        sb.AppendLine("");
      }

      foreach (DataGridViewRow row in dtgrdvwDailyLook.Rows)
      {
        int CellCount = 0;
        foreach (DataGridViewCell cell in row.Cells)
        {
          if (CellCount != 0)
          {
            sb.Append(Delimiter);
          }
          if (cell.Value != null)
          {
            sb.Append(cell.Value.ToString());
          }
          CellCount++;
        }
        sb.AppendLine("");
      }
      return sb;
    }

    private void btnBoost_Click(object sender, EventArgs e)
    {
      if (m_PlayerBuildData.Boost())
      {
        RefreshDailyLookGridRow(dtgrdvwDailyLook.Rows[dtgrdvwDailyLook.Rows.Count - 1]);
        RefreshGoalGrid();
        UpdateLabels();
      }
      else
      {
        Utility.ShowInfoMessage("No remaing boosts.", "No Boosts");
      }
    }

    private void cmbxAutobuild_SelectedIndexChanged(object sender, EventArgs e)
    {
      switch (cmbxAutobuild.Text)
      {
        case "Build to a cap":
          chckbxAutobuildBonusTokens.Enabled = true;
          cmbxAutobuildSkill.Enabled = true;
          cmbxAutobuildTargetCap.Enabled = true;
          spnAutobuildCount.Enabled = false;
          break;
        case "Build to a level":
          lblCount.Text = "Level to build to:";
          chckbxAutobuildBonusTokens.Enabled = false;
          spnAutobuildCount.Maximum = 70;
          spnAutobuildCount.Minimum = 2;
          spnAutobuildCount.Enabled = true;
          cmbxAutobuildSkill.Enabled = false;
          cmbxAutobuildTargetCap.Enabled = false;
          break;
        case "Build for X days":
          lblCount.Text = "Days to build:";
          chckbxAutobuildBonusTokens.Enabled = false;
          spnAutobuildCount.Maximum = 400;
          spnAutobuildCount.Minimum = 2;
          spnAutobuildCount.Enabled = true;
          cmbxAutobuildSkill.Enabled = false;
          cmbxAutobuildTargetCap.Enabled = false;
          break;
      }
    }

    private void btnGo_Click(object sender, EventArgs e)
    {
      if (cmbxAutobuild.Text.Trim() != "")
      {
        if (m_Autobuilding)
        {
          m_StopAutobuild = true;
        }
        else
        {
          //start autobuild.
          if (dtgrdvwTraining.Rows.Count == 0)
          {
            if (Utility.QuestionBox("You have not setup any training.  Do you wish to setup training before processing your Autobuild?", MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
              return;
            }
          }
          StartAutobuild();
        }
      }
      else
      {
        Utility.ShowInfoMessage("Please select an autobuild type", "Select Autobuild");
        cmbxAutobuild.Select();
      }
    }

    private void StartAutobuild()
    {
      try
      {
        //Disable all buttons, except go button.
        EnableButtons(false);
        btnGo.Text = "Stop!";
        //get the total number of training points needed 
        int TPsNecessary = GetTotalTrainingPoints();
        switch (cmbxAutobuild.Text)
        {
          case "Build to a cap":
            double Cap = double.Parse(cmbxAutobuildTargetCap.Text);
            while (!m_StopAutobuild)
            {
              while (m_PlayerBuildData.UnspentTP >= TPsNecessary && TPsNecessary > 0)
              {
                //process daily until you hit cap  
                //ONly process if we have enough training points.
                CommitCurrentChanges(true, false, false);
              }
              StartNewDay();
              DailyLookSelectLastRow();
              //is the cap reachable with ALL SP and Bonus Tokens                     
              PlayerDay pd = m_PlayerBuildData.GetPlayerDay(Utility.GetSeasonDayString(m_PlayerBuildData.Season, m_PlayerBuildData.Day));
              int SPsNeededToReachGoal = GetSPsToGoalAttrLevel(pd.RunningBuildTotals[cmbxAutobuildSkill.Text].CurrentAmount, Cap);
              int SPsAvailable = m_PlayerBuildData.UnspentSP;
              if (chckbxAutobuildBonusTokens.Checked)
              {
                SPsAvailable += (int)Math.Floor((decimal)m_PlayerBuildData.UnspentBT / 4);
              }
              if (SPsAvailable >= SPsNeededToReachGoal)
              {
                break;
              }
              //process daily until you have enough SP to hit a cap.
              //Do we need to boost today?
              while (m_PlayerBuildData.Day == (int)spnBoostDay.Value && m_PlayerBuildData.UnspentBoosts > 0)
              {
                m_PlayerBuildData.Boost();
              }
              Application.DoEvents();
            }
            break;
          case "Build to a level":
            int LevelToBuildTo = (int)spnAutobuildCount.Value;
            while (!m_StopAutobuild)
            {
              while (m_PlayerBuildData.UnspentTP >= TPsNecessary && TPsNecessary > 0)
              {
                //process daily until you hit level  
                //ONly process if we have enough training points.
                CommitCurrentChanges(true, false, false);
              }
              StartNewDay();
              DailyLookSelectLastRow();
              if (m_PlayerBuildData.Level >= LevelToBuildTo)
              {
                break;
              }
              //Do we need to boost today?
              while (m_PlayerBuildData.Day == (int)spnBoostDay.Value && m_PlayerBuildData.UnspentBoosts > 0)
              {
                m_PlayerBuildData.Boost();
              }
              Application.DoEvents();
            }
            break;
          case "Build for X days":
            int DaysCount = 1;
            int DaysToBuild = (int)spnAutobuildCount.Value;
            while (!m_StopAutobuild)
            {
              while (m_PlayerBuildData.UnspentTP >= TPsNecessary && TPsNecessary > 0)
              {
                //process daily until you hit level  
                //ONly process if we have enough training points.
                CommitCurrentChanges(true, false, false);
              }
              StartNewDay();
              DailyLookSelectLastRow();
              DaysCount++;
              if (DaysCount > DaysToBuild)
              {
                break;
              }
              //Do we need to boost today?
              while (m_PlayerBuildData.Day == (int)spnBoostDay.Value && m_PlayerBuildData.UnspentBoosts > 0)
              {
                m_PlayerBuildData.Boost();
              }
              Application.DoEvents();
            }
            break;
        }
      }
      catch
      {
      }
      finally
      {
        m_Autobuilding = false;
        if (m_StopAutobuild)
        {
          Utility.ShowInfoMessage("Autobuilding was stopped before the goal was reached.", "Stop Autobuild");
        }
        m_StopAutobuild = false;
        EnableButtons(true);
        btnGo.Text = "Go!";
      }

    }

    private void DailyLookSelectLastRow()
    {
      if (dtgrdvwDailyLook.Rows.Count > 1)
      {
        dtgrdvwDailyLook.CurrentCell = dtgrdvwDailyLook[0, dtgrdvwDailyLook.Rows.Count - 1];
      }
    }

    /// <summary>
    /// returns the number of TPs needed to process all training in the training grid
    /// </summary>
    /// <returns></returns>
    private int GetTotalTrainingPoints()
    {
      int result = 0;
      for (int RowIndex = 0; RowIndex < dtgrdvwTraining.Rows.Count; RowIndex++)
      {
        switch (dtgrdvwTraining.Rows[RowIndex].Cells[0].Value.ToString())
        {
          case TrainingLevelStrings.NORMAL:
            result += 2;
            break;
          case TrainingLevelStrings.INTENSE:
            result += 5;
            break;
        }
      }
      return result;
    }

    private void EnableButtons(Boolean Enabled)
    {
      btnAddCapGoal.Enabled = Enabled;
      btnAddSkillSP.Enabled = Enabled;
      btnBackupOneDay.Enabled = Enabled;
      btnBoost.Enabled = Enabled;
      btnBTToSP.Enabled = Enabled;
      btnNightlyProcessing.Enabled = Enabled;
      btnProcess.Enabled = Enabled;
      btnProcessGame.Enabled = Enabled;
      btnRemoveCapGoal.Enabled = Enabled;
      btnRemoveSkillSP.Enabled = Enabled;
      btnRemoveTraining.Enabled = Enabled;
      btnTrain.Enabled = Enabled;
      menuStrip1.Enabled = Enabled;
    }

    private void viewApproximateTrainingPercentagesToolStripMenuItem_Click(object sender, EventArgs e)
    {

      if (m_atpForm == null || m_atpForm.IsDisposed)
      {
        m_atpForm = new ApproxTrainingPct(m_PlayerBuildData.GetApproxTrainingPcts());
      }

      if (m_atpForm.Visible)
      {
        m_atpForm.BringToFront();
      }
      else
      {
        m_atpForm.Show(this);
      }
    }

    private void closeToolStripMenuItem_Click(object sender, EventArgs e)
    {
      if (Utility.QuestionBox("Are you sure you wish to close this build screen?", MessageBoxButtons.YesNo) == DialogResult.Yes)
      {
        this.Close();
      }
    }

    private void backupXDaysToolStripMenuItem_Click(object sender, EventArgs e)
    {
      int DaysToRollback = 0;
      using (frmNumDaysToBackup form = new frmNumDaysToBackup(DaysToRollback))
      {
        //automate the backup process.  Start by asking for # of days.
        if (form.ShowDialog() == DialogResult.OK)
        {
          DaysToRollback = form._DaysToBackup;
        }
      }
      if (DaysToRollback > 0)
      {
        for (int index = 1; index <= DaysToRollback; index++)
        {
          if (m_PlayerBuildData.PlayerDays.Count > 2)
          {
            Rollback();
          }
          else
          {
            Utility.ShowInfoMessage("You've reached the beginning of this build", "Beginning Reached");
            break;
          }
        }
      }
    }

    private void spnedtMaxGameXPPct_ValueChanged(object sender, EventArgs e)
    {
    }


    private void toolStripMenuItem3_Click(object sender, EventArgs e)
    {

      saveFileDialog1.Filter = "Player Data Binary|*.bin";
      saveFileDialog1.Title = "Save Build to File";
      saveFileDialog1.FileName = m_PlayerBuildData.PlayerName;
      
      if (saveFileDialog1.ShowDialog() == DialogResult.OK)
      {
        using (System.IO.Stream a = System.IO.File.OpenWrite(saveFileDialog1.FileName))
        {
          System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
          bf.Serialize(a, m_PlayerBuildData);
          a.Close();
        }
        //save off the grid file as well
        try
        {
          string Data = GetGridDelimited("\t", false).ToString();
          string GridFileName = System.IO.Path.ChangeExtension(saveFileDialog1.FileName, ".grd");
          using (System.IO.StreamWriter sr = new System.IO.StreamWriter(GridFileName))
          {
            sr.Write(Data.ToString());
            sr.Flush();
            sr.Close();
          }
        }
        catch (Exception ex)
        {
          Utility.ShowErrorMesssage(ex, string.Format("Unable to save to file {0}", saveFileDialog1.FileName));
        }
      }
    }

    private void toolStripMenuItem4_Click(object sender, EventArgs e)
    {
      if (openFileDialog1.ShowDialog() == DialogResult.OK)
      {
        using (System.IO.FileStream file = new System.IO.FileStream(openFileDialog1.FileName, System.IO.FileMode.Open))
        {

          System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
          m_PlayerBuildData = bf.Deserialize(file) as PlayerBuild;
        }
        cmbxGamesOn.Text = m_PlayerBuildData.GameDays;
        //Refresh everything
        UpdateLabels();
        //clear and refresh the grid
        dtgrdvwDailyLook.Rows.Clear();
        string GridFileName = System.IO.Path.ChangeExtension(openFileDialog1.FileName, ".grd");
        using (System.IO.StreamReader sr = new System.IO.StreamReader(GridFileName))
        {
          string line;
          // Read and display lines from the file until the end of 
          // the file is reached.
          while ((line = sr.ReadLine()) != null)
          {
            string[] columns = line.Split('\t');
            //Add to grid view
            DataGridViewRow dgvr = new DataGridViewRow();
            dgvr.CreateCells(dtgrdvwDailyLook);
            for (int i = 0; i < dgvr.Cells.Count; i++)
            {
              dgvr.Cells[i].Value = columns[i];
            }
            dtgrdvwDailyLook.Rows.Add(dgvr);
          }

        }
      }

    }

    private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
    {

    }

    private void toolStripMenuItem6_Click(object sender, EventArgs e)
    {

    }

    private void cmbxGamesOn_TextChanged(object sender, EventArgs e)
    {
      //update the player data games on
      m_PlayerBuildData.GameDays = cmbxGamesOn.Text;
    }

    private void toolStripMenuItem7_Click(object sender, EventArgs e)
    {
      ++m_PlayerBuildData.UnspentBoosts;
      UpdateLabels();
    }

    private void toolStripMenuItem8_Click(object sender, EventArgs e)
    {
      --m_PlayerBuildData.UnspentBoosts;
      UpdateLabels();
    }

    private void toolStripMenuItem9_Click(object sender, EventArgs e)
    {
      using (frmChangeXPPct frm = new frmChangeXPPct(m_PlayerBuildData.MaxGameXPPct))
      {
        if (frm.ShowDialog() == DialogResult.OK)
        {
          m_PlayerBuildData.MaxGameXPPct = frm.MaxGameXPPct;
          UpdateLabels();
        }
      }
    }

  }

}